<!DOCTYPE html>
<html>
	<head>
		<title>GEDCOM File Reader</title>
		<style type="text/css">
			html {
				height:100%;
				width:100%;
			}
			body {
				margin:0px;
				text-align:center;
				font-family:arial,helvetica,sans-serif;
				height:100%;
				width:100%;
			}
			#container {
				text-align:center;
				position:absolute;
				top:0;
				left:0;
			}
			#row {
				position:absolute;
				overflow:hidden;
			}
			.person {
				text-align:left;
				position:absolute;
				z-index:2;
			}
			.person.unknown {
				color:#a1a1a1;
			}
			#guides {
				position:absolute;
				z-index:1;
			}
			.person h3 {
				font-size:10px;
				line-height:1.2em;
				display:inline;
				background-color:#eeeeee;
				cursor:pointer;
			}
			.person h3:hover {
				background-color:#d3e5ea;
			}
			.person h3.selected {
				background-color:#005271;
				color:#ffffff;
			}
			.person .subtext {
				font-size:8px;
			}
			#menu {
				position:absolute;
				right:0;
				top:0;
				height:100%;
				width:200px;
				padding:20px;
				background-color:#eeeeee;
				z-index:3;
			}
		</style>
		<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
		<script type="text/javascript">
			var data = [];
			var individuals = {};
			var families = {};
			var sources = {};
			var generations;
			function getFamily() {
			$.ajax({
				url:'lustig.ged',
				dataType:'text',
				success: function(result) {
					var data = result.replace(/\r/g,"").split("\n");
					$(data).each(function(i) {
						var strings = data[i].split(" ",2);
						strings[2] = data[i].replace(strings[0]+" "+strings[1],"");
						if (strings[2].substring(0,1) == " ") {
							strings[2] = strings[2].substring(1,strings[2].length);
						} 
						if (strings[2].substring(strings[2].length-1,1) == " ") {
							strings[2] = strings[2].substring(0,strings[2].length-1);
						}
						data[i] = strings;
					});
					$(data).each(function(i) {
						if (data[i][0] == "0" && data[i][1] != "HEAD" && data[i][1] != "TRLR") {
							var item = {};
							var id = data[i][1];
							var j = i+1;
							var parent = item;
							var stack = [item];
							while (data[j][0] != 0) {
								var num = data[j][0];
								var code = lookUp(data[j][1]);
								var value = data[j][2];
								stack[num] = code;
								for (k=0;k<=parseInt(num)-1;k++) {
									if (k == 0) {
										parent = item;
									} else {
										if (parent[stack[k]].splice) {
											parent = parent[stack[k]][parent[stack[k]].length-1];
										} else {
											parent = parent[stack[k]];
										}
									}
								}
								if (data[j+1][0] > num) {
									if (parent[code] != undefined) {
										if (parent[code].splice) {
											parent[code].push({});
											if (value != "") {
												parent[code][parent[code].length-1]["Value"] = value;
											}
										} else {
											parent[code] = new Array(parent[code],{})
											if (value != "") {
												parent[code][1]["Value"] = value;
											}
										}
									} else {
										parent[code] = {};
										if (value != "") {
											parent[code]["VAL"] = value;
										}
									}
								} else {
									if (parent[code] != undefined) {
										if (parent[code].splice) {
											parent[code].push(value);
										} else {
											parent[code] = new Array(parent[code],value)
										}
									} else {																										parent[code] = value;
									}
								}
								j++;
							}
							switch(data[i][2]) {
								case "FAM ":
									families[id] = item;
									break;
								case "INDI ":
									individuals[id] = item;
									break;
								case "SOUR":
									sources[id] = item;
								default:
									break;
							}
						}
					});
					individuals.UNKN = {'Name':'Unknown'};
					drawFamily();
				}
			});
			}
				function drawFamily() {
					var personid = '@P1@';
					var person = individuals[personid];
					var people = [];
					var count = 2;
					var rowcount = 0;
					var indcount = 1;
					var fams = findValue(person.FAMS);
					var famc;
					for (key in individuals) {
						if (key == families[fams].HUSB || key == families[fams].WIFE) {
							people.push(key);
						}
					}
					var basewidth = 200;
					var indwidth = basewidth;
					var baseheight = 30;
					var indheight,indtop,indleft;
					var displayheight = Math.pow(2,generations)*baseheight;
					for (i = 0;i<(Math.pow(2,generations)+(Math.pow(2,generations)-2));i++) {
						indcount++;
						indheight = displayheight/count; 
						indtop = indheight*(indcount-2);
						indleft = indwidth*rowcount;
						person = individuals[people[i]];
						famc = findValue(person.FAMC);
						if (families[famc] != undefined) {
							var wife = false;
							var husband = false;
							for (key in individuals) {
								if (key == families[famc].HUSB) {
									people.push(key);
									husband = true;
								}
								if (key == families[famc].WIFE) {
									people.push(key);
									wife = true;
								}
							}
							if (husband != true) {
								people.push("UNKN");
							}
							if (wife != true) {
								people.push("UNKN");
							}
						} else {
							people.push("UNKN","UNKN");
						}
						var bdate;
						if (person.Birth != undefined) {
							bdate = person.Birth.Date;
						} else {
							bdate = "";
						} 
						var ddate;
						if (person.Death != undefined) {
							ddate = person.Death.Date;
						} else {
							ddate = "";
						}
						$('#container').append($('<div class="person" id="'+people[i]+'">')
							.css('width',basewidth+'px')
							.css('height',baseheight+'px')
							.css('padding',(indheight-baseheight)/2+'px 0px')
							.css('top',indtop+'px')
							.css('left',indleft+'px')
							.html('<h3>'+findValue(person.Name).replace(/\//g,"")+'</h3>'
								+ '<div class="subtext">'+bdate+' - '+ddate+'</div>'
							)
						);
						$('#container').append($('<canvas id="guides" width="'+indwidth+'" height="'+indheight+'">')
							.css('top',indtop+'px')
							.css('left',indleft+'px')
						);
						if (rowcount+1 != generations) {
							var ctx = $('canvas#guides')[$('canvas#guides').length-1].getContext('2d');
							ctx.strokeStyle = "#cccccc";
							ctx.beginPath();
							if (rowcount != 0) {
								ctx.moveTo(indwidth/2,indheight/2);
								ctx.lineTo(0,indheight/2);
							}
							ctx.moveTo(indwidth/2,indheight/2);
							ctx.lineTo(indwidth,indheight/4);
							ctx.moveTo(indwidth/2,indheight/2);
							ctx.lineTo(indwidth,3*(indheight/4));
							ctx.closePath();
							ctx.stroke();
						}
						if (name == "Unknown") {
							$('div#person').last().addClass('unknown');
						}
						if (indcount > count) {
							rowcount++;
							indcount = 1;
							count *= 2;
						}	
					}
				}
			$(document).delegate('.person h3','click',function() {
				$('.person h3').removeClass('selected');
				$(this).addClass('selected');
				var person = individuals[$(this).parent().attr('id')]
				$('#info').html(findValue(person.Name));
				var values = [];
				if (person.Birth != undefined) {
					values.push(findValue(person.Birth.Date));
					values.push(findValue(person.Birth.Place));
				}
				for (i in values) {
					if (findValue(values[i]) != undefined) {
						$('#info').html($('#info').html()+"<br />"+findValue(values[i]));
					}
				}
			});
			$(document).ready(function() {
				$('body').mousedown(function(click) {
					$('#container').css('cursor','move');
					var x = click.pageX;
					var y = click.pageY;
					var left = parseInt($('#container').css('left'));
					var top = parseInt($('#container').css('top'));
					$(this).mouseup(function() {
						$(this).unbind('mousemove');
						$('#container').css('cursor','auto');
					});
					$(this).mousemove(function(e) {
						$('#container').css('left',(left+(e.pageX-x))+"px");
						$('#container').css('top',(top+(e.pageY-y))+"px");
					});
				});
				$('#gens').change(function() {
					generations = $('#gens option:selected').val();
					$('#container').html("").css('left','0').css('top','0');
					drawFamily();
				});
				generations = $('#gens option:selected').val();
				getFamily();
			});
			var lookup = {
				"NAME":"Name",
				"BIRT":"Birth",
				"SOUR":"Source",
				"DATE":"Date",
				"TEXT":"Text",
				"NOTE":"Note",
				"PLAC":"Place",
				"CONT":"Content",
				"SEX":"Gender",
				"RESI":"Residence",
				"OCCU":"Occupation",
				"PAGE":"Page",
				"DEAT":"Death"
			};
			function lookUp(val) {
				if (lookup[val] != undefined) {
					return lookup[val];
				} else {
					return val;
				}
			}
			function findValue(val) {
				if (val != undefined) {
					if (typeof(val) == "string") {
						return val;
					} else {
						if (val.VAL != undefined) {
							return val.VAL;
						} else {
							return val[0].VAL;
						}
					}
				} else {
					return undefined;
				}
			}
		</script>
	</head>
	<body>
		<div id="menu">
			<select id="gens">
				<option val="3" selected>3</option>
				<option val="4">4</option>
				<option val="5">5</option>
				<option val="6">6</option>
				<option val="7">7</option>
				<option val="8">8</option>
				<option val="9">9</option>
				<option val="10">10</option>
			</select>
			<div id="info"></div>
		</div>
		<div id="container"></div>
	</body>
</html>